package io.itit.ecp.admin.provide.helper;

import com.alibaba.ttl.TransmittableThreadLocal;
import io.itit.ecp.admin.common.constants.EcpAdminConstants;
import io.itit.ecp.admin.common.constants.ParamConstants;
import io.itit.ecp.admin.common.enums.IDataRangeEnums;
import io.itit.ecp.admin.provide.helper.datarangelevel.AbsDataRangeLevelHelper;
import io.itit.ecp.admin.provide.properties.DataRangeConfigProperties;
import io.itit.ecp.admin.server.entity.DataRangeEntity;
import io.itit.ecp.admin.server.entity.UserDataRangeEntity;
import io.itit.ecp.admin.server.service.IDataRangeService;
import io.itit.ecp.admin.server.service.IUserDataRangeService;
import io.itit.grass.common.exception.GrassException;
import io.itit.grass.common.server.helper.RedisHelper;
import io.itit.grass.web.wall.service.IUserLoginAfterService;
import io.itit.grass.web.wall.utils.ShiroUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.function.Supplier;

/*
 **********************
 * @Author Roy
 * @ClassName SceneHelper
 * @Description 数据范围辅助类
 * @Date 2024/01/09 10:34
 **********************
 **/
@Component
public class DataRangeHelper implements InitializingBean, IUserLoginAfterService {

    private static final ThreadLocal<Boolean> TEMPORARY_TOKEN = new TransmittableThreadLocal<>();

    @Resource
    private RedisHelper redisHelper;

    @Resource
    private IDataRangeService dataRangeService;

    @Resource
    private IUserDataRangeService userDataRangeService;

    @Resource
    private DataRangeConfigProperties dataRangeConfigProperties;

    @Resource
    private List<AbsDataRangeLevelHelper> absDataRangeLevelHelperList;

    private static DataRangeHelper dataRangeHelper;

    public static DataRangeHelper i() {

        return dataRangeHelper;
    }

    /**
     * 设置当前回调函数内的数据处理不受数据范围权限限制
     *
     * @param supplier
     * @param <T>
     * @return
     */
    public <T> T approve(Supplier<T> supplier) {
        try {
            set();
            return supplier.get();
        } finally {
            //释放
            remove();
        }
    }

    /**
     * 当前线程 >>> 校验令牌状态
     */
    public boolean has() {
        return TEMPORARY_TOKEN.get() == null ? false : TEMPORARY_TOKEN.get();
    }

    /**
     * 当前线程 >>> 设置令牌
     * 设置当前线不做数据范围权限拦截
     */
    public boolean set() {
        if (!check()) {
            return false;
        }
        TEMPORARY_TOKEN.set(true);
        return TEMPORARY_TOKEN.get();
    }

    /**
     * 当前线程 >>> 销毁令牌
     * 返回销毁前的值
     */
    public Boolean remove() {
        if (!check()) {
            return false;
        }
        Boolean token = TEMPORARY_TOKEN.get();
        TEMPORARY_TOKEN.remove();
        return token;
    }

    /**
     * 判断开关是否打开
     *
     * @return
     */
    public boolean check() {
        return dataRangeConfigProperties.getEnable() != null && dataRangeConfigProperties.getEnable();
    }

    /**
     * 用户登录之后初始化数据范围权限
     */
    @Override
    public void process() {
        initDataRange(ShiroUtils.getUserId());
    }

    /**
     * 初始化数据范围权限
     *
     * @param userId
     * @return
     */
    public String initDataRange(String userId) {
        UserDataRangeEntity userDataRange = userDataRangeService.lambdaQuery()
                .eq(UserDataRangeEntity::getUserId, userId)
                .last(ParamConstants.LIMIT_ONE)
                .one();
        if (userDataRange == null) {
            petDataRangeLevel(userId, EcpAdminConstants.NO);
            return EcpAdminConstants.NO;
        }

        DataRangeEntity dataRange = dataRangeService.lambdaQuery()
                .eq(DataRangeEntity::getId, userDataRange.getDataRangeId())
                .eq(DataRangeEntity::getStatus, IDataRangeEnums.Status.status1.status)
                .one();
        if (userDataRange == null) {
            petDataRangeLevel(userId, EcpAdminConstants.NO);
            return EcpAdminConstants.NO;
        }
        petDataRangeLevel(userId, dataRange.getRangeLevel());

        // 如果有所有数据范围权限就无需处理数据
        if (IDataRangeEnums.RangeLevel.rangeLevelAll.rangeLevel.equals(dataRange.getRangeLevel())) {
            return dataRange.getRangeLevel();
        }

        // 缓存数据范围
        dataRangeLevelHelper(dataRange.getRangeLevel()).processDataRange(dataRange.getId());
        return dataRange.getRangeLevel();
    }

    public AbsDataRangeLevelHelper dataRangeLevelHelper(String rangeLevel) {
        for (AbsDataRangeLevelHelper absDataRangeLevelHelper : absDataRangeLevelHelperList) {
            if (absDataRangeLevelHelper.rangeLevel().rangeLevel.equals(rangeLevel)) {
                return absDataRangeLevelHelper;
            }
        }
        throw new GrassException("未匹配到数据范围级别配置");
    }

    /**
     * 删除缓存中的用户数据权限
     *
     * @param userId
     * @return
     */
    public void removeDataRangeCache(String userId) {
        redisHelper.delete(EcpAdminConstants.DATA_RANGE_LEVEL, userId);
    }

    /**
     * 设置数据范围级别
     *
     * @param userId
     * @param rangeLevel
     */
    public void petDataRangeLevel(String userId, String rangeLevel) {
        redisHelper.put(EcpAdminConstants.DATA_RANGE_LEVEL, userId, rangeLevel);
    }


    /**
     * 获取当前登录用户的数据范围级别
     */
    public String getDataRangeLevel() {
        return getDataRangeLevel(ShiroUtils.getUserId());
    }


    /**
     * 获取数据范围级别
     *
     * @param userId
     */
    public String getDataRangeLevel(String userId) {
        return redisHelper.get(EcpAdminConstants.DATA_RANGE_LEVEL, userId);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        dataRangeHelper = this;
    }
}
